package middleware

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"

	"awesomeProject/app/model"
	"awesomeProject/global"
)

func Operation() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		var body []byte
		user, _ := ctx.Get("user")
		userCache := user.(model.User)
		if ctx.Request.Method != http.MethodGet {
			body, _ = ioutil.ReadAll(ctx.Request.Body)
			ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
		}
		record := model.OperationRecord{
			OperationRecordFillAble: model.OperationRecordFillAble{
				ReqUri:    ctx.Request.RequestURI,
				ReqMethod: ctx.Request.Method,
				ReqIP:     ctx.ClientIP(),
				ReqBody:   string(body),
				UserAgent: ctx.Request.UserAgent(),
				CreatedBy: userCache.ID,
			},
		}

		writer := responseBodyWriter{
			ResponseWriter: ctx.Writer,
			body:           &bytes.Buffer{},
		}
		ctx.Writer = writer
		now := time.Now()

		ctx.Next()

		// 中间件执行完成后续
		latency := time.Now().Sub(now)
		record.ErrMsg = ctx.Errors.ByType(gin.ErrorTypePrivate).String()
		record.Status = ctx.Writer.Status()
		record.Latency = latency
		record.Resp = writer.body.String()

		global.Gorm.Model(&model.OperationRecord{}).Create(&record)
	}
}

type responseBodyWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (r responseBodyWriter) Write(b []byte) (int, error) {
	r.body.Write(b)
	return r.ResponseWriter.Write(b)
}
